package cc.facesign.admin.service.impl;

import cc.facesign.admin.bean.TblConf;
import cc.facesign.admin.bean.TblConfUser;
import cc.facesign.admin.bean.fv.confupload.ConfSimpleFv;
import cc.facesign.admin.bean.fv.confupload.UserSimpleChildFv;
import cc.facesign.admin.bean.query.ConfQuery;
import cc.facesign.admin.bean.vo.ConfVo;
import cc.facesign.admin.bean.vo.DeptVo;
import cc.facesign.admin.bean.vo.UserSignVo;
import cc.facesign.admin.bean.vo.UserVo;
import cc.facesign.admin.enums.ConfStatusType;
import cc.facesign.admin.mapper.TblConfMapper;
import cc.facesign.admin.service.*;
import cc.facesign.admin.utils.RedisKey;
import cc.facesign.common.type.RoleType;
import cc.facesign.servicebase.utils.RedisCache;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author testjava
 * @since 2022-05-06
 */
@Service
@Transactional
public class TblConfServiceImpl extends ServiceImpl<TblConfMapper, TblConf> implements TblConfService {

    @Autowired
    private TblDeptService deptService;

    @Autowired
    private TblUserService userService;
    @Autowired
    private AclService aclService;

    @Autowired
    private TblConfUserService confUserService;

    @Autowired
    private TblConfService confService;

    @Autowired
    private RedisCache redisCache;


    @Override
    public ConfVo getInfoById(String confId) {
        ConfVo vo = baseMapper.getInfoById(confId);
        vo.setStatusText(ConfStatusType.codeOf(vo.getStatus()));
        return vo;
    }

    @Override
    public List<ConfVo> getListByQuery(ConfQuery query) {
        List<ConfVo> list = baseMapper.getListByQuery(query);
        for (ConfVo vo : list) {
            Integer status = vo.getStatus();
            vo.setStatusText(ConfStatusType.codeOf(status));
        }
        return list;
    }

    @Override
    public List<ConfVo> getChildListByDeptId(String deptId) {
        // 获取部门id列表
        List<String> ids = deptService.getChildListByDeptId(deptId).stream()
                .map(DeptVo::getId)
                .collect(Collectors.toList());

        List<ConfVo> res = new ArrayList<>();
        for (TblConf e : list(null)) {
            if (ids.contains(e.getDeptId())) {
                ConfVo vo = getInfoById(e.getId());
                res.add(vo);
            }
        }

        return res;
    }

    @Override
    public List<UserSignVo> getUserSignListByConfId(String id) {
        return baseMapper.getUserSignListByConfId(id);
    }

    @Override
    public Map<String, Object> getConfSignInfoByConfId(String id) {
        List<UserSignVo> userList = getUserSignListByConfId(id);
        int total = getById(id).getTotal();
        int sign = 0;

        List<String> ids = new ArrayList<>();
        List<String> idsSuccess = new ArrayList<>();
        for (UserSignVo user : userList) {
            if (user.getIsSign() == 0) ids.add(user.getUserId());
            else {
                sign++;
                idsSuccess.add(user.getUserId());
            }
        }

        List<UserVo> noSignUserList = userService.getInfoByIdBatch(ids);
        List<UserVo> signUserList = userService.getInfoByIdBatch(idsSuccess);

        Map<String, Integer> mapSign = userList.stream()
                .collect(Collectors.toMap(x -> x.getUserId(), x -> x.getIsSign()));
        for (UserVo e : noSignUserList) {
            Integer state = mapSign.get(e.getId());
            e.setIsSign(state);
        }
        for (UserVo e : signUserList) {
            Integer state = mapSign.get(e.getId());
            e.setIsSign(state);
        }

        Map<String, Object> map = new HashMap<>();
        map.put("total", total);
        map.put("sign", sign);
        map.put("no-sign", total - sign);
        map.put("sign-userList", signUserList);
        map.put("no-sign-userList", noSignUserList);

        return map;
    }

    @Override
    public List<ConfVo> getListByDeptIdBatch(List<String> strings) {
        List<ConfVo> list = baseMapper.getListByDeptIdBatch(strings);
        for (ConfVo vo : list) {
            Integer status = vo.getStatus();
            vo.setStatusText(ConfStatusType.codeOf(status));
        }
        return list;
    }

    @Override
    public List<UserVo> getUserListByConfId(String id) {
        QueryWrapper<TblConfUser> w = new QueryWrapper<>();
        w.eq("conf_id", id);
        List<String> userIds = confUserService.list(w).stream()
                .map(TblConfUser::getUserId)
                .collect(Collectors.toList());

        return userService.getInfoByIdBatch(userIds);
    }

    @Override
    public Set<String> getNoSignUserSetByConfId(String id) {
        List<UserVo> list = (List<UserVo>) getConfSignInfoByConfId(id).get("no-sign-userList");
        return list.stream()
                .map(UserVo::getId)
                .collect(Collectors.toCollection(HashSet::new));
    }

    @Override
    public void addUserByIds(String confId, List<String> ids) {
        List<TblConfUser> relateList = new ArrayList<>();
        for (String id : ids) {
            TblConfUser t = new TblConfUser();
            t.setConfId(confId);
            t.setUserId(id);
            t.setIsSign(0);
            relateList.add(t);
        }

        // 用户加入关联表
        confUserService.saveOrUpdate(relateList);

        // 更新conf表total值
        updateTotal(confId);
    }

    @Override
    public int updateTotal(String confId) {
        QueryWrapper<TblConfUser> w = new QueryWrapper<>();
        w.eq("conf_id", confId);
        int count = confUserService.count(w);

        TblConf conf = getById(confId);
        conf.setTotal(count);
        updateById(conf);

        return count;

    }

    @Override
    public String createCode() {
        Set<String> codeSet = list(null).stream()
                .map(x -> x.getCode())
                .collect(Collectors.toSet());

        String code;
        Random random = new Random();
        do {
            code = "";
            for (int i = 0; i < 6; i++) {
                code += random.nextInt(10);
            }
        } while (codeSet.contains(code));
        return code;
    }

    @Override
    public List<UserVo> getUserInfoContainsSignByConfId(String confId) {
        List<UserSignVo> list = getUserSignListByConfId(confId);

        // key:userId value:isSign
        Map<String, Integer> map = list.stream()
                .collect(Collectors.toMap(x -> x.getUserId(), x -> x.getIsSign()));

        List<String> ids = list.stream()
                .map(x -> x.getUserId())
                .collect(Collectors.toList());

        List<UserVo> vos = userService.getInfoByIdBatch(ids);
        for (UserVo vo : vos) {
            Integer state = map.get(vo.getId());
            vo.setIsSign(state);
        }

        return vos;
    }

    @Override
    public ConfVo getInfoByCode(String code) {
        QueryWrapper<TblConf> w = new QueryWrapper<>();
        w.eq("code", code);
        TblConf one = getOne(w);

        return getInfoById(one.getId());
    }

    @Override
    public void removeConfById(String id) {
        List<String> ids = getUserListByConfId(id).stream()
                .map(x -> x.getId())
                .collect(Collectors.toList());

        confUserService.deleteBatch(id, ids);
        removeById(id);
    }

    @Override
    public void removeUsers(String confId, List<String> ids) {
        confUserService.deleteBatch(confId, ids);
    }

    @Override
    public ConfSimpleFv getSimpleInfo(String confId, List<String> ids) {
        List<UserVo> infos = userService.getInfoByIdBatch(ids);

        TblConf conf = getById(confId);
        ConfSimpleFv res = new ConfSimpleFv();
        res.setMid(conf.getCode());
        List<UserSimpleChildFv> childs = new ArrayList<>();
        for (UserVo e : infos) {
            childs.add(new UserSimpleChildFv(e.getCardId(), e.getAvatar()));
        }
        res.setImgs(childs);
        return res;
    }

    @Override
    public ConfSimpleFv getSimpleInfoAll(String confId) {
        // 获取会议中所有用户id
        List<String> userIds = getUserListByConfId(confId).stream()
                .map(x -> x.getId())
                .collect(Collectors.toList());

        return getSimpleInfo(confId, userIds);
    }

    @Override
    public void stop(String confId) {
        TblConf conf = confService.getById(confId);

        // 修改会议状态为已结束
        conf.setStatus(4);
        confService.updateById(conf);

        // 清空会议-角色关联，数据存入redis
        QueryWrapper<TblConfUser> w = new QueryWrapper<>();
        w.eq("conf_id", confId);
        List<UserVo> userList = confService.getUserInfoContainsSignByConfId(confId);
        redisCache.setCacheList(RedisKey.CONF_END_USERINFO+confId, userList);
        confUserService.remove(w);

        // 逻辑删除会议
        confService.removeById(confId);

        // 更新角色
        aclService.deleteManage(conf.getCreaterId(), deptService.getRid(conf.getDeptId()), RoleType.CONF );
    }


}
